
#include "pch.h"
#include"chart.h"


void Recognition::get_cross_xy(double slope0, double offset0, double slope1, double offset1, double & cross_x, double & cross_y)
{
	cross_x = (offset0 - offset1) / (slope1 - slope0);
	cross_y = (offset1*slope0 - offset0 * slope1) / (slope0 - slope1);
}

int Recognition::get_target_center(BYTE * bin, int w, int h, int pattern_size, int corner_size, int & center_x, int & center_y, int * edge_x, int * edge_y)
{
	int x1 = 0, x2 = 0;
	int y1 = 0, y2 = 0;
	BYTE *p = NULL;

	for (int j = 0; j < h - (pattern_size - 1); j++) {
		for (int i = 0; i < w - (pattern_size - 1); i++) {
			p = bin + j * w + i;
			if (is_pattern_qualified(p, w, h, pattern_size, corner_size, FALSE)) {
				get_pattern_center(p, w, h, pattern_size, center_x, center_y, edge_x, edge_y);
				center_x += i; edge_x[0] += i; edge_x[1] += i; edge_x[2] += i; edge_x[3] += i;
				center_y += j; edge_y[0] += j; edge_y[1] += j; edge_y[2] += j; edge_y[3] += j;
				return TRUE;
			}
		}
	}

	for (int j = 0; j < h - (pattern_size - 1); j++) {
		for (int i = 0; i < w - (pattern_size - 1); i++) {
			p = bin + j * w + i;
			if (is_pattern_qualified(p, w, h, pattern_size, corner_size, TRUE)) {
				get_pattern_center(p, w, h, pattern_size, center_x, center_y, edge_x, edge_y);
				center_x += i; edge_x[0] += i; edge_x[1] += i; edge_x[2] += i; edge_x[3] += i;
				center_y += j; edge_y[0] += j; edge_y[1] += j; edge_y[2] += j; edge_y[3] += j;
				return TRUE;
			}
		}
	}

	return 0;
}

int Recognition::is_pattern_qualified(BYTE *p, int w, int h, int pattern_size, int corner_size, int s_white)
{
	if ((corner_size * 2) >= pattern_size) return FALSE;

	int result = TRUE;
	if (s_white == FALSE) {
		for (int j = 0; j < corner_size; j++) {
			for (int i = 0; i < corner_size; i++) {
				if (p[j*w + i] == ABS_WHITE) return FALSE;
				if (p[j*w + i + (pattern_size - corner_size)] == ABS_BLACK) return FALSE;
				if (p[(j + (pattern_size - corner_size))*w + i] == ABS_BLACK) return FALSE;
				if (p[(j + (pattern_size - corner_size))*w + i + (pattern_size - corner_size)] == ABS_WHITE) return FALSE;
			}
		}
	}
	else {
		for (int j = 0; j < corner_size; j++) {
			for (int i = 0; i < corner_size; i++) {
				if (p[j*w + i] == ABS_BLACK) return FALSE;
				if (p[j*w + i + (pattern_size - corner_size)] == ABS_WHITE) return FALSE;
				if (p[(j + (pattern_size - corner_size))*w + i] == ABS_WHITE) return FALSE;
				if (p[(j + (pattern_size - corner_size))*w + i + (pattern_size - corner_size)] == ABS_BLACK) return FALSE;
			}
		}
	}

	return TRUE;
}

void Recognition::get_pattern_center(BYTE * p, int w, int h, int p_size, int & x, int & y, int * px, int * py)
{
	int x1 = 0, y1 = 0;
	int x2 = 0, y2 = 0;

	for (int m = 0; m < p_size - 1; m++) {
		if (p[m] != p[m + 1]) { x1 = m; break; }
	}
	for (int m = 0; m < p_size - 1; m++) {
		if (p[(p_size - 1)*w + m] != p[(p_size - 1)*w + m + 1]) { x2 = m; break; }
	}

	x = (x1 + x2) / 2;
	px[0] = x1;
	px[1] = p_size - 1;
	px[2] = x2;
	px[3] = 0;

	for (int m = 0; m < p_size - 1; m++) {
		if (p[m*w] != p[(m + 1)*w]) { y1 = m; break; }
	}
	for (int m = 0; m < p_size - 1; m++) {
		if (p[m*w + (p_size - 1)] != p[(m + 1)*w + (p_size - 1)]) { y2 = m; break; }
	}
	y = (y1 + y2) / 2;
	py[0] = 0;
	py[1] = y2;
	py[2] = p_size - 1;
	py[3] = y1;

}

void Recognition::Release(void)
{
	delete[] buf;
}

//Paint

Paint::Paint()
{
	font_size = 10;
	axis_x_offset[0] = -5;
	axis_x_offset[1] = 5;
	axis_x_offset[2] = 10;
	axis_x_offset[3] = 5;

	axis_y_offset[0] = -30;
	axis_y_offset[1] = -6;
	axis_y_offset[2] = -30;
	axis_y_offset[3] = -20;
}

HDC Paint::create(HWND hdlg, int cx, int cy, int first_x, int last_x, int first_y, int last_y, COLORREF cr)
{
	RECT rt;
	GetClientRect(hdlg, &rt);

	drawing_size[0] = cx;
	drawing_size[1] = cy;
	begin_offset[0] = first_x;
	begin_offset[1] = first_y;
	end_offset[0] = last_x;
	end_offset[1] = last_y;
	full_size[0] = begin_offset[0] + drawing_size[0] + end_offset[0];
	full_size[1] = begin_offset[1] + drawing_size[1] + end_offset[1];
	dlg_size[0] = rt.right - rt.left;
	dlg_size[1] = rt.bottom - rt.top;

	hdc = GetDC(hdlg);
	//DeleteObject(hbitmap);
	hbitmap = CreateCompatibleBitmap(hdc, dlg_size[0], dlg_size[1]);
	HDC memdc = CreateCompatibleDC(hdc);
	HBITMAP old_bitmap = (HBITMAP)SelectObject(memdc, hbitmap);

	HBRUSH mybrush = CreateSolidBrush(cr);
	FillRect(memdc, &rt, mybrush);
	DeleteObject(mybrush);

	old_map_mode = SetMapMode(memdc, MM_ANISOTROPIC);
	SetViewportOrgEx(memdc, 0, 0, NULL);
	SetViewportExtEx(memdc, dlg_size[0], dlg_size[1], NULL);
	SetWindowExtEx(memdc, full_size[0], full_size[1], NULL);

	SetBkMode(memdc, TRANSPARENT);
	SelectObject(memdc, GetStockObject(NULL_BRUSH));

	//hbitmap = NULL;
	return memdc;
}

void Paint::draw_axis_x_int(HDC hdc, int factor, int interval, const char * str, int start_x, int multi, COLORREF cr)
{
	//assert(factor != 0 && interval != 0);
	HPEN pen = CreatePen(PS_DOT, 1, cr);
	HPEN old_pen = (HPEN)SelectObject(hdc, pen);
	HFONT font = CreateFont(font_size, 0, 0, 0, FW_BLACK, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, L"Arial");
	HFONT old_font = (HFONT)SelectObject(hdc, font);

	char buffer[10] = { 0 };
	int cnt = drawing_size[0] / (factor*interval);

	//draw x;
	for (int i = 0; i < cnt + 1; i++) {
		if (str != NULL) {
			sprintf(buffer, "%02d", (start_x + i * interval)*multi);
			TextOutA(hdc, begin_offset[0] + i * factor*interval + axis_x_offset[0], full_size[1] - begin_offset[1] + axis_x_offset[1], buffer, strlen(buffer));
		}

		MoveToEx(hdc, begin_offset[0] + i * interval*factor, full_size[1] - begin_offset[1], NULL);
		LineTo(hdc, begin_offset[0] + i * factor*interval, full_size[1] - (begin_offset[1] + drawing_size[1]));
	}
	if (str != NULL) {
		strcpy(buffer, str);
		TextOutA(hdc, begin_offset[0] + drawing_size[0] + axis_x_offset[2], full_size[1] - begin_offset[1] + axis_x_offset[3], buffer, strlen(buffer));
	}

	DeleteObject(pen);
	DeleteObject(font);
}

void Paint::draw_axis_x_int_interval(HDC hdc, int factor, int interval, const char * str, int start_x, int multi, COLORREF cr)
{
	//assert(factor != 0 && interval != 0);
	HPEN pen = CreatePen(PS_DOT, 1, cr);
	HPEN old_pen = (HPEN)SelectObject(hdc, pen);
	HFONT font = CreateFont(font_size, 0, 0, 0, FW_BLACK, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, L"Arial");
	HFONT old_font = (HFONT)SelectObject(hdc, font);

	char buffer[10] = { 0 };
	int cnt = drawing_size[0] / (factor*interval);

	//draw x;
	for (int i = 0; i < cnt + 1; i++) {
		if (str != NULL && (i % 2 == 0)) {
			sprintf(buffer, "%02d", start_x + i * multi);
			TextOutA(hdc, begin_offset[0] + i * factor*interval + axis_x_offset[0], full_size[1] - begin_offset[1] + axis_x_offset[1], buffer, strlen(buffer));
		}

		MoveToEx(hdc, begin_offset[0] + i * interval*factor, full_size[1] - begin_offset[1], NULL);
		LineTo(hdc, begin_offset[0] + i * factor*interval, full_size[1] - (begin_offset[1] + drawing_size[1]));
	}
	if (str != NULL) {
		strcpy(buffer, str);
		TextOutA(hdc, begin_offset[0] + drawing_size[0] + axis_x_offset[2], full_size[1] - begin_offset[1] + axis_x_offset[3], buffer, strlen(buffer));
	}

	DeleteObject(pen);
	DeleteObject(font);
}

void Paint::draw_axis_y_int(HDC hdc, int factor, int interval, const char * str, int start_y, int multi, COLORREF cr)
{
	//assert(factor != 0 && interval != 0);
	HPEN pen = CreatePen(PS_DOT, 1, cr);
	HPEN old_pen = (HPEN)SelectObject(hdc, pen);
	HFONT font = CreateFont(font_size, 0, 0, 0, FW_BLACK, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, L"Arial");
	HFONT old_font = (HFONT)SelectObject(hdc, font);

	char buffer[10] = { 0 };
	int cnt = drawing_size[1] / (int)(factor*interval);
	//draw y;
	for (int i = 0; i < cnt + 1; i++) {
		if (str != NULL) {
			sprintf(buffer, "%d", (start_y + i * interval)*multi);
			TextOutA(hdc, begin_offset[0] + axis_y_offset[0], full_size[1] - (begin_offset[1] + i * factor*interval) + axis_y_offset[1], buffer, strlen(buffer));
		}
		MoveToEx(hdc, begin_offset[0], full_size[1] - (begin_offset[1] + i * factor*interval), NULL);
		LineTo(hdc, begin_offset[0] + drawing_size[0], full_size[1] - (begin_offset[1] + i * factor*interval));
	}
	if (str != NULL) {
		strcpy(buffer, str);
		TextOutA(hdc, begin_offset[0] + axis_y_offset[2], full_size[1] - (begin_offset[1] + drawing_size[1]) + axis_y_offset[3], buffer, strlen(buffer));
	}

	DeleteObject(pen);
	DeleteObject(font);
}

void Paint::draw_axis_x_float(HDC hdc, float factor, float interval, const char * str, float start_x, float multi, COLORREF cr)
{
	//assert(factor != 0.0f && interval != 0.0f);
	HPEN pen = CreatePen(PS_DOT, 1, cr);
	HPEN old_pen = (HPEN)SelectObject(hdc, pen);
	HFONT font = CreateFont(font_size, 0, 0, 0, FW_BLACK, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, L"Arial");
	HFONT old_font = (HFONT)SelectObject(hdc, font);

	char buffer[10] = { 0 };
	int cnt = drawing_size[0] / (int)(factor*interval);
	//	XTRACE("axis_x_offset[0]=%d\n", axis_x_offset[0]);
		//draw x;
	for (int i = 0; i < cnt + 1; i++) {
		if (str != NULL) {
			sprintf(buffer, "%.2f", (start_x + (float)i*interval)*multi);
			TextOutA(hdc, begin_offset[0] + (int)(i*factor*interval) + axis_x_offset[0], full_size[1] - begin_offset[1] + axis_x_offset[1], buffer, strlen(buffer));
			//	XTRACE("x=%f, ", factor);
		}
		MoveToEx(hdc, begin_offset[0] + (int)(i*factor*interval), full_size[1] - begin_offset[1], NULL);
		LineTo(hdc, begin_offset[0] + (int)(i*factor*interval), full_size[1] - (begin_offset[1] + drawing_size[1]));
	}
	//	XTRACE("\n");
	if (str != NULL) {
		strcpy(buffer, str);
		TextOutA(hdc, begin_offset[0] + drawing_size[0] + axis_x_offset[2], full_size[1] - begin_offset[1] + axis_x_offset[3], buffer, strlen(buffer));
	}

	DeleteObject(pen);
	DeleteObject(font);
}

void Paint::draw_axis_y_float(HDC hdc, float factor, float interval, const char * str, float start_y, float multi, COLORREF cr)
{
	//assert(factor != 0.0f && interval != 0.0f);
	HPEN pen = CreatePen(PS_DOT, 1, cr);
	HPEN old_pen = (HPEN)SelectObject(hdc, pen);
	HFONT font = CreateFont(font_size, 0, 0, 0, FW_BLACK, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, L"Arial");
	HFONT old_font = (HFONT)SelectObject(hdc, font);

	char buffer[10] = { 0 };
	int cnt = drawing_size[1] / (int)(factor*interval);
	//draw y;
	for (int i = 0; i < cnt + 1; i++) {
		if (str != NULL) {
			sprintf(buffer, "%.2f", (start_y + (float)i*interval)*multi);
			TextOutA(hdc, begin_offset[0] + axis_y_offset[0], full_size[1] - (begin_offset[1] + (int)(i*factor*interval)) + axis_y_offset[1], buffer, strlen(buffer));
		}
		MoveToEx(hdc, begin_offset[0], full_size[1] - (begin_offset[1] + (int)(i*factor*interval)), NULL);
		LineTo(hdc, begin_offset[0] + drawing_size[0], full_size[1] - (begin_offset[1] + (int)(i*factor*interval)));
	}
	if (str != NULL) {
		strcpy(buffer, str);
		TextOutA(hdc, begin_offset[0] + axis_y_offset[2], full_size[1] - (begin_offset[1] + drawing_size[1]) + axis_y_offset[3], buffer, strlen(buffer));
	}

	DeleteObject(pen);
	DeleteObject(font);
}

void Paint::release(HWND hdlg, HDC memdc)
{
	SetMapMode(memdc, old_map_mode);
	SetStretchBltMode(hdc, HALFTONE);
	BitBlt(hdc, 0, 0, dlg_size[0], dlg_size[1], memdc, 0, 0, SRCCOPY);

	DeleteObject(hbitmap);
	DeleteDC(memdc);
	ReleaseDC(hdlg, hdc);
}

void Paint::set_axis(int my_font_size, int * my_axis_x_offset, int * my_axis_y_offset)
{
	font_size = my_font_size;
	for (int i = 0; i < 4; i++) {
		axis_x_offset[i] = my_axis_x_offset[i];
		axis_y_offset[i] = my_axis_y_offset[i];
	}
}

void DirPath::LoadKey(const char *path, const char *section, HWND hdlg, INIEdit *edit, int item_count)
{
	char buffer[MAX_PATH] = { 0 };
	int hex_val = 0;
	for (int i = 0; i < item_count; i++)
	{
		if (edit[i].idc == NULL && edit[i].type == NULL && edit[i].var == NULL && edit[i].var == NULL) break;
		GetPrivateProfileStringA(section, edit[i].name, NULL, buffer, MAX_PATH, path);
		switch (edit[i].type)
		{
		//case DLGTYPE_CHECK_BOOL:
		//	*((int *)(edit[i].var)) = atoi(buffer);
		//	if (hdlg == NULL) break;
		//	SendDlgItemMessage(hdlg, edit[i].idc, BM_SETCHECK, atoi(buffer) ? BST_CHECKED : BST_UNCHECKED, 0);
		//	break;

		case DLGTYPE_INPUT_INT:
			*((int *)(edit[i].var)) = atoi(buffer);
			if (hdlg == NULL) break;
			SetDlgItemTextA(hdlg, edit[i].idc, buffer);
			break;

		case DLGTYPE_INPUT_FLOAT:
			*((float *)(edit[i].var)) = atof(buffer);
			if (hdlg == NULL) break;
			SetDlgItemTextA(hdlg, edit[i].idc, buffer);
			break;

		//case DLGTYPE_INPUT_DOUBLE:
		//	*((double *)(edit[i].var)) = atof(buffer);
		//	if (hdlg == NULL) break;
		//	SetDlgItemTextA(hdlg, edit[i].idc, buffer);
		//	break;

		case DLGTYPE_INPUT_STRING:
			strcpy((char *)(edit[i].var), buffer);
			if (hdlg == NULL) break;
			SetDlgItemTextA(hdlg, edit[i].idc, buffer);
			break;

		//case DLGTYPE_INPUT_HEX:
		//	sscanf(buffer, "%hx", &hex_val);
		//	*((int *)(edit[i].var)) = hex_val;
		//	memset(buffer, 0, sizeof(buffer));
		//	sprintf(buffer, "%02x", hex_val);
		//	if (hdlg == NULL) break;
		//	SetDlgItemTextA(hdlg, edit[i].idc, buffer);
		//	break;

		//case DLGTYPE_COMBO_INT:
		//	*((int *)(edit[i].var)) = atoi(buffer);
		//	if (hdlg == NULL) break;
		//	SendDlgItemMessage(hdlg, edit[i].idc, CB_SETCURSEL, atoi(buffer), 0L);
		//	break;

		//case DLGTYPE_INPUT_HEX4:
		//	sscanf(buffer, "%hx", &hex_val);
		//	*((int *)(edit[i].var)) = hex_val;
		//	memset(buffer, 0, sizeof(buffer));
		//	sprintf(buffer, "%04x", hex_val);
		//	if (hdlg == NULL) break;
		//	SetDlgItemTextA(hdlg, edit[i].idc, buffer);
		//	break;

		//case DLGTYPE_RADIO_BOOL:
		//{
		//	int idc_1 = LOWORD(edit[i].idc);
		//	int idc_2 = HIWORD(edit[i].idc);
		//	*((int *)(edit[i].var)) = atoi(buffer);
		//	if (hdlg == NULL) break;
		//	if (atoi(buffer) == 0) {
		//		SET_CHECKER_ON(hdlg, idc_1);
		//		SET_CHECKER_OFF(hdlg, idc_2);
		//	}
		//	else {
		//		SET_CHECKER_ON(hdlg, idc_2);
		//		SET_CHECKER_OFF(hdlg, idc_1);
		//	}
		//}
		//break;
		}
	}
}

void DirPath::SaveKey(const char *path, const char *section, HWND hdlg, INIEdit *edit, int item_count)
{
	char buffer[MAX_PATH] = { 0 };
	BOOL is_checked = FALSE;
	char hex[20] = { 0 };
	for (int i = 0; i < item_count; i++)
	{
		if (edit[i].idc == NULL && edit[i].type == NULL && edit[i].var == NULL && edit[i].var == NULL) break;

		switch (edit[i].type)
		{
		//case DLGTYPE_CHECK_BOOL:
		//	if (edit[i].idc != NULL) {
		//		is_checked = (int)SendDlgItemMessage(hdlg, edit[i].idc, BM_GETCHECK, 0, 0);
		//		*((int *)(edit[i].var)) = (is_checked ? 1 : 0);
		//		WritePrivateProfileStringA(section, edit[i].name, (is_checked ? "1" : "0"), path);
		//	}
		//	break;

		case DLGTYPE_INPUT_INT:
			if (edit[i].idc != NULL) {
				GetDlgItemTextA(hdlg, edit[i].idc, buffer, MAX_PATH);
				*((int *)(edit[i].var)) = atoi(buffer);
				WritePrivateProfileStringA(section, edit[i].name, buffer, path);
			}
			//else {
			//	WritePrivateProfileString(section, edit[i].name, *((int *)(edit[i].var)), path);
			//}
			break;

		case DLGTYPE_INPUT_FLOAT:
			if (edit[i].idc != NULL) {
				GetDlgItemTextA(hdlg, edit[i].idc, buffer, MAX_PATH);
				*((float *)(edit[i].var)) = atof(buffer);
				WritePrivateProfileStringA(section, edit[i].name, buffer, path);
			}
			//else {
			//	write_float_key(path, section, edit[i].name, *((float *)(edit[i].var)));
			//}
			break;

		//case DLGTYPE_INPUT_DOUBLE:
		//	if (edit[i].idc != NULL) {
		//		GetDlgItemTextA(hdlg, edit[i].idc, buffer, MAX_PATH);
		//		*((double *)(edit[i].var)) = atof(buffer);
		//		WritePrivateProfileStringA(section, edit[i].name, buffer, path);
		//	}
		//	//else {
		//	//	write_float_key(path, section, edit[i].name, *((float *)(edit[i].var)));
		//	//}
		//	break;

		case DLGTYPE_INPUT_STRING:
			if (edit[i].idc != NULL) {
				GetDlgItemTextA(hdlg, edit[i].idc, buffer, MAX_PATH);
				strcpy((char *)(edit[i].var), buffer);
				WritePrivateProfileStringA(section, edit[i].name, buffer, path);
			}
			//else {
			//	write_string_key(path, section, edit[i].name, (char *)(edit[i].var));
			//}

			break;

		//case DLGTYPE_INPUT_HEX:
		//case DLGTYPE_INPUT_HEX4:
		//	if (edit[i].idc != NULL) {
		//		GetDlgItemTextA(hdlg, edit[i].idc, buffer, MAX_PATH);
		//		sprintf(hex, "0X%s", buffer);
		//		WritePrivateProfileStringA(section, edit[i].name, hex, path);
		//	}
		//	break;

		//case DLGTYPE_COMBO_INT:
		//	if (edit[i].idc != NULL) {
		//		*((int *)(edit[i].var)) = COMBO_GETCURSEL(hdlg, edit[i].idc);
		//		sprintf(buffer, "%d", *((int *)(edit[i].var)));
		//		WritePrivateProfileStringA(section, edit[i].name, buffer, path);
		//	}
		//	else {
		//		sprintf(buffer, "%d", *((int *)(edit[i].var)));
		//		WritePrivateProfileStringA(section, edit[i].name, buffer, path);
		//	}
		//	break;
		//case DLGTYPE_RADIO_BOOL:
		//	if (edit[i].idc != NULL) {
		//		int b = GET_CHECKER(hdlg, LOWORD(edit[i].idc));
		//		*((int *)(edit[i].var)) = (b ? 0 : 1);
		//		sprintf(buffer, "%d", *((int *)(edit[i].var)));
		//		WritePrivateProfileStringA(section, edit[i].name, buffer, path);
		//	}
		//	break;
		}
	}
}

void DirPath::GetCurrentDir(char *path)
{
	if (path == NULL) return;
	GetModuleFileNameA(NULL, path, MAX_PATH);
	char *p = strrchr(path, '\\');
	*p = '\0';
}

BOOL DirPath::SearchFile(const char * path, const char * name)
{
	WIN32_FIND_DATAA wfd;

	char search_path[MAX_PATH] = { 0 };
	sprintf(search_path, "%s\\*.*", path);
	HANDLE search = FindFirstFileA(search_path, &wfd);

	char search_name[MAX_PATH] = { 0 };
	strcpy(search_name, name);

	BOOL finding = TRUE;
	while (finding) {
		if (wfd.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) {
			int n = strlen(wfd.cFileName);
			for (int i = 0; i < n; i++) {
				wfd.cFileName[i] = (char)toupper((int)wfd.cFileName[i]);
			}

			n = strlen(search_name);
			for (int i = 0; i < n; i++) {
				search_name[i] = (char)toupper((int)search_name[i]);
			}
			//uppercase(wfd.cFileName);
			//uppercase(search_name);
			if (!strcmp(wfd.cFileName, search_name)) {
				FindClose(search);
				return TRUE;
			}
		}
		finding = FindNextFileA(search, &wfd);
	}

	FindClose(search);
	return 0;
}

